package nl.tue.be.ds.duraark.bSDD.dump;

import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import nl.tue.be.ds.duraark.bSDD.DataBaseStorageUnit;
import nl.tue.be.ds.duraark.bSDD.DataBaseUtilities;

import org.codehaus.jackson.JsonNode;

public class StorageUnitDumpCallable implements Callable<Integer> {
	JsonNode jsonConcepts;
	
	public StorageUnitDumpCallable(JsonNode jsonConcepts) {
		super();
		this.jsonConcepts = jsonConcepts;
	}

	public Integer call() throws Exception {
		Integer i = dumpSearchedConcepts(jsonConcepts);
		return i;
	}

	private int dumpSearchedConcepts(JsonNode jsonConcepts) {
		int conceptCounter = 0;
		
		if (jsonConcepts != null) {

			if (jsonConcepts.isArray()) {
				Iterator<JsonNode> it = jsonConcepts.iterator();
				while (it.hasNext()) {
					JsonNode jsonNode = it.next();
					boolean b = DataBaseUtilities.isConceptExistedInDB(jsonNode, DataBaseUtilities.db);
					if(!b){
						
						DataBaseStorageUnit dbStorageUnit = getDBStorageUnit(jsonNode);
						
						System.out.println("Concept with this Guid just be dumped : "+ dbStorageUnit.getGuid());
						//
						if (dbStorageUnit.getParentsGuidMap()== null)
							System.out.println("No parents rels");
						else{
							Iterator<String> iter = dbStorageUnit.getParentsGuidMap().keySet().iterator();
							while(iter.hasNext()){
								String conceptGuid = (String) iter.next();
								System.out.println("Parents rels: "+ conceptGuid + "<---->" + dbStorageUnit.getParentsGuidMap().get(conceptGuid));
							}
						}
						if (dbStorageUnit.getChildrenGuidMap()== null)
							System.out.println("No children rels");
						else
						{
							Iterator<String> iter = dbStorageUnit.getChildrenGuidMap().keySet().iterator();
							while(iter.hasNext()){
								String conceptGuid = (String) iter.next();
								System.out.println("Children rels: "+ conceptGuid + "<---->" + dbStorageUnit.getChildrenGuidMap().get(conceptGuid));
							}
						}
						//		
						DataBaseUtilities.db.store(dbStorageUnit);
						conceptCounter++;
						}
					}
			} else {
				boolean b = DataBaseUtilities.isConceptExistedInDB(jsonConcepts,DataBaseUtilities.db);
				if(!b){
					
					DataBaseStorageUnit dbStorageUnit = getDBStorageUnit(jsonConcepts);
					
					System.out.println("Concept with this Guid just be dumped : " + dbStorageUnit.getGuid());
					//
					if (dbStorageUnit.getParentsGuidMap()== null)
						System.out.println("No parents rels");
					else{
						Iterator<String> iter = dbStorageUnit.getParentsGuidMap().keySet().iterator();
						while(iter.hasNext()){
							String conceptGuid = (String) iter.next();
							System.out.println("Parents rels: "+ conceptGuid + "<---->" + dbStorageUnit.getParentsGuidMap().get(conceptGuid));
						}
					}
					if (dbStorageUnit.getChildrenGuidMap()== null)
						System.out.println("No children rels");
					else
					{
						Iterator<String> iter = dbStorageUnit.getChildrenGuidMap().keySet().iterator();
						while(iter.hasNext()){
							String conceptGuid = (String) iter.next();
							System.out.println("Children rels: "+ conceptGuid + "<---->" + dbStorageUnit.getChildrenGuidMap().get(conceptGuid));
						}
					}
					//
					DataBaseUtilities.db.store(dbStorageUnit);
					conceptCounter++;
					
				}
			}	
				
		}
		return conceptCounter;
	}
	
	private DataBaseStorageUnit getDBStorageUnit(JsonNode jsonNode) {
		
		DataBaseStorageUnit dbStorageUnit = new DataBaseStorageUnit() ;
		
		String guid = jsonNode.get("guid").getTextValue();
		dbStorageUnit.setGuid(guid);
		dbStorageUnit.setConceptJN(jsonNode);
		setParentsRels(guid, dbStorageUnit);
		setChildrenRels(guid, dbStorageUnit);
		
		return dbStorageUnit;
	}
	
	
	private void setParentsRels(String guid, DataBaseStorageUnit dumpStorageUnit){
		
		RelSearchPerGuidCallable parentsCrc = new RelSearchPerGuidCallable(guid, "parents");
		ExecutorService threadPool = Executors.newSingleThreadExecutor();
		Future<HashMap<String, String>> parentsf = threadPool.submit(parentsCrc);
		
		HashMap<String, String> relsMap = getRels(parentsf, 0);	
		dumpStorageUnit.setParentsGuidMap(relsMap);
		
		threadPool.shutdown();
		
	}
	
	private void setChildrenRels(String guid, DataBaseStorageUnit dumpStorageUnit){
		
		RelSearchPerGuidCallable childrenCrc = new RelSearchPerGuidCallable(guid, "children");
		ExecutorService threadPool = Executors.newSingleThreadExecutor();
		Future<HashMap<String, String>> childrenf = threadPool.submit(childrenCrc);
		
		HashMap<String, String> relsMap = getRels(childrenf, 0);	
		dumpStorageUnit.setChildrenGuidMap(relsMap);
		
		threadPool.shutdown();
		
	}
	
	private HashMap<String, String> getRels(Future<HashMap<String, String>> future, int recDep){
		HashMap<String, String> relsMap = new HashMap<String, String>();
		
		if (recDep < 10) {
			try {
				relsMap = future.get();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				relsMap = getRels(future, recDep + 1);
			}
		} /*else {
			relsMap.put(DataBaseUtilities.stringGuidForRelOverflow, DataBaseUtilities.stringGuidForRelOverflow);
		}*/
		return relsMap;
	}

	
}
